package org.zjvis.datascience.common.util;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.StringUtils;
import org.zjvis.datascience.common.dto.TaskDTO;
import org.zjvis.datascience.common.dto.TaskInstanceDTO;
import org.zjvis.datascience.common.enums.TaskTypeEnum;
import org.zjvis.datascience.common.widget.dto.WidgetDTO;

import java.util.List;

/**
 * @description pipeline数据流图帮助类
 * @date 2021-12-01
 */
public class PipelineUtil {

    public static boolean checkTaskIfConfig(String dataJson) {
        if (StringUtils.isEmpty(dataJson)) {
            return false;
        }
        JSONObject jsonObject = JSONObject.parseObject(dataJson);
        return checkTaskIfConfig(jsonObject);
    }

    public static boolean checkTaskIfConfig(JSONObject dataJsonObject) {
        JSONArray output = dataJsonObject.getJSONArray("output");
        if (output == null || output.size() == 0
                || output.getJSONObject(0).getJSONArray("tableCols") == null) {
            //前2个条件:节点没有配置。第三个条件:filter算子没有配置
            return false;
        }
        JSONObject outputObject = output.getJSONObject(0);
        String tableName = outputObject.getString("tableName");
        //DBSCAN,FP_GROWTH,PREFIX_SPAN未配置参数
        if (StringUtils.isEmpty(tableName) || tableName.endsWith("null_")) {
            return false;
        }
        return true;
    }

    /**
     * 从taskInstance中提取出待删除的视图或表
     *
     * @param taskInstanceDTOs
     * @param returnTables     提取结果存放的list
     * @return
     */
    public static boolean extractTableName(List<TaskInstanceDTO> taskInstanceDTOs,
                                           List<String> returnTables) {
        if (ObjectUtil.isEmpty(taskInstanceDTOs)) {
            return false;
        }
        boolean isView = false;
        for (TaskInstanceDTO taskInstanceDTO : taskInstanceDTOs) {
            //待删除的视图
            if (StringUtils.isEmpty(taskInstanceDTO.getLogInfo())) {
                String sqlText = taskInstanceDTO.getSqlText();
                if (StringUtils.isEmpty(sqlText)) {
                    continue;
                }
                if (sqlText.toUpperCase().startsWith("CREATE VIEW")) {
                    String tableName = sqlText.split(" ")[2];
                    returnTables.add(tableName);
                    isView = true;
                } else if (sqlText.toLowerCase().contains("sys_func_pivot_table_view_create")) {
                    String tableName = sqlText.split(",")[1].replace("'", "");
                    returnTables.add(tableName);
                    isView = true;
                }
                if (sqlText.toUpperCase().startsWith("CREATE TABLE")) {
                    String tableName = sqlText.split(" ")[2];
                    returnTables.add(tableName);
                    isView = false;
                }
            } else {//待删除的表
                String logInfo = taskInstanceDTO.getLogInfo();
                JSONObject jsonObject = JSONObject.parseObject(logInfo);
                JSONObject result = jsonObject.getJSONObject("result");
                if (result == null || !result.containsKey("output_params")) {
                    continue;
                }
                JSONArray outputs = result.getJSONArray("output_params");
                for (int j = 0; j < outputs.size(); j++) {
                    JSONObject obj = outputs.getJSONObject(j);
                    String tableName = obj.getString("out_table_name");
                    if (StringUtils.isNotEmpty(tableName)) {
                        returnTables.add(tableName);
                    }
                }
            }
        }
        return isView;
    }

    public static JSONArray extractOutPut(TaskDTO parentTask, TaskInstanceDTO parentIns) {
        JSONObject parentData = JSONObject.parseObject(parentTask.getDataJson());
        JSONArray parentOutPut = parentData.getJSONArray("output");
        //修改表名为真正的表名
        if (parentTask.getType() != TaskTypeEnum.TASK_TYPE_CLEAN.getVal()
                || parentTask.getType() != TaskTypeEnum.TASK_TYPE_DATA.getVal()) {
            List<String> list = Lists.newArrayList();
            PipelineUtil.extractTableName(Lists.newArrayList(parentIns), list);
            for (int i = 0; i < list.size(); i++) {
                for (int j = 0; j < parentOutPut.size(); j++) {
                    JSONObject jObject = parentOutPut.getJSONObject(j);
                    if (list.get(i).startsWith(jObject.getString("tableName"))) {
                        jObject.put("tableName", list.get(i));
                    }
                }
            }
        }
        return parentOutPut;
    }

    public static List<WidgetDTO> extractBindWidgets(List<WidgetDTO> taskWidgets,
                                                     TaskInstanceDTO remove) {
        if (CollectionUtil.isEmpty(taskWidgets)) {
            return null;
        }
        List<WidgetDTO> list = Lists.newArrayList();
        JSONObject actionData = JSONObject.parseObject(remove.getDataJson());
        Long removeId = actionData.getLong("id");
        for (WidgetDTO widget : taskWidgets) {
            JSONObject widgetData = JSONObject.parseObject(widget.getDataJson());
            JSONObject formData = widgetData.getJSONObject("formData");
            if (null != formData) {
                String dataType = formData.getString("dataType");
                Long dataId = formData.getLong("dataId");
                if ("tclean".equals(dataType) && removeId.equals(dataId)) {
                    list.add(widget);
                }
            }
        }
        return list;
    }

    /**
     * 将清洗历史操作封成undo用的json
     *
     * @param action
     * @param index
     * @return
     */
    public static List<JSONObject> parseJSONObject(TaskInstanceDTO action, int index) {
        List<JSONObject> list = Lists.newArrayList();
        JSONObject item = (JSONObject) JSONObject.toJSON(action);
        item.put("index", index);
        list.add(item);
        return list;
    }
}
